Expand description

clone-replace

A CloneReplace is a synchronisation primitive that provides owned handles for shared data.

Example:

use clone_replace::CloneReplace;

let data = CloneReplace::new(1);

let v1 = data.access();
assert_eq!(*v1, 1);
{
   let mut m = data.mutate();
   *m = 2;
   let v2 = data.access();
   assert_eq!(*v1, 1);
   assert_eq!(*v2, 1);
}
let v3 = data.access();
assert_eq!(*v3, 2);
assert_eq!(*v1, 1);

This is a primitive in a similar format to Mutex, in that it wraps data for thread-safety, and provides access via guards. A shared, reference copy of the data is stored. When reading, a handle to an immutable snapshot state is obtained, as an Arc. All readers who access this version of the data will receive handles to the same snapshot.

To mutate the data, the reference copy is cloned into a mutable guard object. The writer is free to make whatever changes they wish to this copy, and the new data will become the reference copy for all subsequent reads and writes, whenever the guard is dropped. No writes are visible whilst the guard is in scope.

This is a somewhat niche primitive that has the following properties:

  • Readers can work with a coherent view for an extended period of time, without preventing writers from making updates, or other readers from seeing those updates.
  • There are no lifetimes to plumb through for the guards: the data is owned. This is most significant before generic associated types stabilise, but it will remain an advantage for the simplicity of some use cases, compared to Mutex or RwLock.
  • Mutation is expensive. A full copy is made every time you create a mutation guard by calling mutate on CloneReplace.
  • The memory overhead can be large. For scenarios with very long running readers, you may end up with many copies of your data being stored simultaneously.
  • In the presence of multiple writers, it’s entirely possible to lose updates, because multiple writers are not prevented from existing at the same time. Whatever state is set will always be internally consistent, but you give up guaranteed external consistency.

Structs

A shareable store for data which provides owned references.

A handle to a writeable version of the data.